﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Numerics;

namespace Fractals
{
    public partial class Form2 : Form
    {
        Bitmap mandelbrotBitmap;
        Bitmap juliaSetBitmap;
        FractalGenerator fractalGenerator;
        Complex lastJuliaSetComplex;

        public Form2()
        {
            fractalGenerator = new FractalGenerator();
            lastJuliaSetComplex = new Complex();
            
            InitializeComponent();

            fractalGenerator.MaxIterations = (int)numericUpDownMaxIterations.Value;
            comboBoxColoringMode.SelectedIndex = 5;

            mandelbrotBitmap = new Bitmap(interpolatedPictureBoxMandelbrot.Width, interpolatedPictureBoxMandelbrot.Height);
            juliaSetBitmap = new Bitmap(interpolatedPictureBoxJuliaSet.Width, interpolatedPictureBoxJuliaSet.Height);

            interpolatedPictureBoxMandelbrot.Image = mandelbrotBitmap;
            interpolatedPictureBoxJuliaSet.Image = juliaSetBitmap;

            fractalGenerator.GenerateMandelbrotImage(mandelbrotBitmap);
            fractalGenerator.GenerateJuliaSetImage(juliaSetBitmap, lastJuliaSetComplex);
        }

        private void createNewJuliaSet(object sender, MouseEventArgs e)
        {
            var pixcoordX = e.X;
            var pixcoordY = e.Y;

            // we have to remap this to the layout of the mandelbrot set coordinate frame
            // real on x ranging [-2, 1]
            // imaginary on y [-1, 1]            
            double real = ((double)pixcoordX / interpolatedPictureBoxMandelbrot.Width) * 3.0 - 2.0;
            double imaginary = ((double)pixcoordY / interpolatedPictureBoxMandelbrot.Height) * 2.0 - 1.0;

            lastJuliaSetComplex = new Complex(real, imaginary);

            // update the image of the juliaSet
            fractalGenerator.GenerateJuliaSetImage(juliaSetBitmap, lastJuliaSetComplex);
            interpolatedPictureBoxJuliaSet.Refresh();

            // change Headline
            labelJuliaSetHeadline.Text = "Julia Set "
                + String.Format("{0,2:+0.0000;-0.0000}", real)
                + " " + String.Format("{0,2:+0.0000;-0.0000}", imaginary) + " i";
        }

        private void changeShading(object sender, EventArgs e)
        {
            if (radioButtonNormalShading.Checked)
            {
                fractalGenerator.SmoothShading = false;
                radioButtonSmoothShading.Checked = false;
            }
            else
            {
                fractalGenerator.SmoothShading = true;
                radioButtonNormalShading.Checked = false;
            }
            redrawMandelbrot(sender, e);
            redrawJuliaSet(sender, e);
        }

        private void changeColoring(object sender, EventArgs e)
        {
            fractalGenerator.ColorMode = comboBoxColoringMode.SelectedIndex;
            redrawMandelbrot(sender, e);
            redrawJuliaSet(sender, e);
        }

        private void saveMandelbrotToFile(object sender, EventArgs e)
        {
            saveImageToFile(mandelbrotBitmap);
        }

        private void saveJuliaSetToFile(object sender, EventArgs e)
        {
            saveImageToFile(juliaSetBitmap);
        }

        private void saveImageToFile(Image image)
        {
            // Displays a SaveFileDialog so the user can save the Image
            SaveFileDialog saveFileDialog1 = new SaveFileDialog();
            saveFileDialog1.Filter = "PNG Image|*.png|JPeg Image|*.jpg|Bitmap Image|*.bmp";
            saveFileDialog1.Title = "Save image to file";
            saveFileDialog1.ShowDialog();

            // If the file name is not an empty string open it for saving.
            if (saveFileDialog1.FileName != "")
            {
                // Saves the Image via a FileStream created by the OpenFile method.
                System.IO.FileStream fs =
                   (System.IO.FileStream)saveFileDialog1.OpenFile();
                // Saves the Image in the appropriate ImageFormat based upon the
                // File type selected in the dialog box.
                // NOTE that the FilterIndex property is one-based.
                switch (saveFileDialog1.FilterIndex)
                {
                    case 1:
                        image.Save(fs,
                           System.Drawing.Imaging.ImageFormat.Png);
                        break;

                    case 2:
                        image.Save(fs,
                           System.Drawing.Imaging.ImageFormat.Jpeg);
                        break;

                    case 3:
                        image.Save(fs,
                           System.Drawing.Imaging.ImageFormat.Bmp);
                        break;
                }

                fs.Close();
            }
        }

        private void changeMaxIterations(object sender, EventArgs e)
        {
            fractalGenerator.MaxIterations = (int)numericUpDownMaxIterations.Value;
            redrawMandelbrot(sender, e);
            redrawJuliaSet(sender, e);
        }

        private void redrawMandelbrot(object sender, EventArgs e)
        {
            mandelbrotBitmap = new Bitmap(interpolatedPictureBoxMandelbrot.Width, interpolatedPictureBoxMandelbrot.Height);
            interpolatedPictureBoxMandelbrot.Image = mandelbrotBitmap;
            fractalGenerator.GenerateMandelbrotImage(mandelbrotBitmap);
        }

        private void redrawJuliaSet(object sender, EventArgs e)
        {
            juliaSetBitmap = new Bitmap(interpolatedPictureBoxJuliaSet.Width, interpolatedPictureBoxJuliaSet.Height);
            interpolatedPictureBoxJuliaSet.Image = juliaSetBitmap;
            fractalGenerator.GenerateJuliaSetImage(juliaSetBitmap, lastJuliaSetComplex);
        }

        private void updateCursorPos(object sender, MouseEventArgs e)
        {
            var pixcoordX = e.X;
            var pixcoordY = e.Y;

            // we have to remap this to the layout of the mandelbrot set coordinate frame
            // real on x ranging [-2, 1]
            // imaginary on y [-1, 1]            
            double real = ((double)pixcoordX / interpolatedPictureBoxMandelbrot.Width) * 3.0 - 2.0;
            double imaginary = ((double)pixcoordY / interpolatedPictureBoxMandelbrot.Height) * 2.0 - 1.0;

            labelRealVal.Text = String.Format("{0,2:+0.0000;-0.0000}", real);
            labelImagVal.Text = String.Format("{0,2:+0.0000;-0.0000}", imaginary) + " i";

            if (checkBoxExplorerMode.Checked)
                createNewJuliaSet(sender, e);
            
        }
    }
}
